package org.jadelyre.core;

import org.jadelyre.core.exception.JadeLyreException;
import org.jadelyre.jade.JadeServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketOption;
import java.net.StandardSocketOptions;
import java.util.HashMap;
import java.util.Map;

/**
 * 线程池参数不给默认参数是出于作者认为这是很重要的，
 * 希望使用者通过了解去自己配置以达到当下业务的最优
 */
public class JadeLyreConfig {
    private static final Logger logger = LoggerFactory.getLogger(JadeLyreConfig.class);
    private static int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();

    public static int availableProcessors(){
        return AVAILABLE_PROCESSORS;
    }

    /**
     * 系统处理socket层面的连接，数据包投递接收等的线程池大小
     */
    private int systemPoolSize;
    /**
     * 共享型业务线程池大小，就是将：
     * decodePoolSize，
     * handlePoolSize，
     * writePoolSize，
     * closePoolSize，
     * 共用一个线程池，
     * 如果配置了灵活的线程池则不会用到
     */
    private int sharedPoolSize;
    /**
     * 任务型线程池独立开来，考虑到任务与业务的隔离性所以剥离开来
     */
    private int scheduledPoolSize;
    /**
     * 灵活的线程池配置
     */
    //解码，一般解码很快的
    private int decodePoolSize;
    //业务处理，根据业务场景分配，但是一般来说业务都是比较耗时的所以可以配置大一点
    private int handlePoolSize;
    //写数据，一般很快的
    private int writePoolSize;
    //处理一些关闭，很快，可以小点
    private int closePoolSize;

    /**
     * socket选项配置
     */
    private Map<SocketOption<?>,Object> socketOptions;

    /**
     * 从socket中读取数据到readBuffer，readBuffer大小根据业务场景灵活设置会有很大优化空间
     */
    private int readBufferSize = 2048;

    public int getSystemPoolSize() {
        if (systemPoolSize <=0 ){
            throw new JadeLyreException("systemPoolSize 参数必须大于0");
        }
        return systemPoolSize;
    }

    public void setSystemPoolSize(int systemPoolSize) {
        if (systemPoolSize <=0 ){
            throw new JadeLyreException("systemPoolSize 参数必须大于0");
        }
        this.systemPoolSize = systemPoolSize;
    }

    public int getSharedPoolSize() {
        if (sharedPoolSize <=0){
            throw new JadeLyreException("sharedPoolSize 参数必须大于0");
        }
        return sharedPoolSize;
    }

    public void setSharedPoolSize(int sharedPoolSize) {
        if (sharedPoolSize <=0){
            throw new JadeLyreException("sharedPoolSize 参数必须大于0");
        }
        this.sharedPoolSize = sharedPoolSize;
    }

    public int getScheduledPoolSize() {
        if (scheduledPoolSize <=0){
            throw new JadeLyreException("scheduledPoolSize 参数必须大于0");
        }
        return scheduledPoolSize;
    }

    public void setScheduledPoolSize(int scheduledPoolSize) {
        if (scheduledPoolSize <=0){
            throw new JadeLyreException("scheduledPoolSize 参数必须大于0");
        }
        this.scheduledPoolSize = scheduledPoolSize;
    }

    public int getDecodePoolSize() {
        if (decodePoolSize <=0){
            throw new JadeLyreException("decodePoolSize 参数必须大于0");
        }
        return decodePoolSize;
    }

    public void setDecodePoolSize(int decodePoolSize) {
        if (decodePoolSize <=0){
            throw new JadeLyreException("decodePoolSize 参数必须大于0");
        }
        this.decodePoolSize = decodePoolSize;
    }

    public int getHandlePoolSize() {
        if (handlePoolSize <=0){
            throw new JadeLyreException("handlePoolSize 参数必须大于0");
        }
        return handlePoolSize;
    }

    public void setHandlePoolSize(int handlePoolSize) {
        if (handlePoolSize <=0){
            throw new JadeLyreException("handlePoolSize 参数必须大于0");
        }
        this.handlePoolSize = handlePoolSize;
    }

    public int getWritePoolSize() {
        if (writePoolSize <=0){
            throw new JadeLyreException("writePoolSize 参数必须大于0");
        }
        return writePoolSize;
    }

    public void setWritePoolSize(int writePoolSize) {
        if (writePoolSize <=0){
            throw new JadeLyreException("writePoolSize 参数必须大于0");
        }
        this.writePoolSize = writePoolSize;
    }

    public int getClosePoolSize() {
        if (closePoolSize <=0){
            throw new JadeLyreException("closePoolSize 参数必须大于0");
        }
        return closePoolSize;
    }

    public void setClosePoolSize(int closePoolSize) {
        if (closePoolSize <=0){
            throw new JadeLyreException("closePoolSize 参数必须大于0");
        }
        this.closePoolSize = closePoolSize;
    }

    public int getReadBufferSize() {
        return readBufferSize;
    }

    public void setReadBufferSize(int readBufferSize) {
        if (readBufferSize <= 0){
            throw new JadeLyreException("readBufferSize 参数必须大于0");
        }
        if (readBufferSize < 512){
            if (logger.isWarnEnabled()){
                logger.warn("readBufferSize 参数最好不要设置小于1024，请确认业务确实合适当前参数");
            }
        }
        this.readBufferSize = readBufferSize;
    }

    public Map<SocketOption<?>, Object> getSocketOptions() {
        if (socketOptions == null || socketOptions.isEmpty()){
            socketOptions = defaultSocketOption();
        }
        return socketOptions;
    }

    public void setSocketOptions(Map<SocketOption<?>, Object> socketOptions) {
        this.socketOptions = socketOptions;
    }

    public boolean isFlexible(){
        return decodePoolSize >0
                &&handlePoolSize>0
                &&writePoolSize>0
                &&closePoolSize>0;
    }

    /**
     * 默认是socket选项
     * @return
     */
    private Map<SocketOption<?>, Object> defaultSocketOption(){
        Map<SocketOption<?>, Object> socketOptionMap = new HashMap<>();
        socketOptionMap.put(StandardSocketOptions.SO_KEEPALIVE, true);
        socketOptionMap.put(StandardSocketOptions.SO_SNDBUF, 64*1024);
        socketOptionMap.put(StandardSocketOptions.SO_RCVBUF, 64*1024);
        socketOptionMap.put(StandardSocketOptions.SO_REUSEADDR, true);
        socketOptionMap.put(StandardSocketOptions.TCP_NODELAY, true);
        return socketOptionMap;
    }
}
